// Macro.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include <iostream>
#include "Macro.h"
#include <string>

enum MyEnum
{
    right,
    left
};

enum MyEnum1
{
	top,
	//left /** 编译报错，left重定义 [8/26/2020 ZC] */
};

const std::string LexToString(int Ename)
{
	switch (Ename)
	{
#define REGISTER_NAME(num,namestr) case num: return #namestr;
#include "Macro.inl"
		/*REGISTER_NAME(0, None)
		REGISTER_NAME(1, ByteProperty)
		REGISTER_NAME(2, IntProperty)
		REGISTER_NAME(3, BoolProperty)
		REGISTER_NAME(4, FloatProperty)*/
#undef REGISTER_NAME
	default:
		return "*INVALID*";
	}
}

struct FGameplayAttributeData
{
	float BaseValue;
	float CurrentValue;

	FGameplayAttributeData()
		: BaseValue(0.f)
		, CurrentValue(0.f)
	{}

	float GetCurrentValue() const
	{
		return CurrentValue;
	}
};
/**
 *	行继续操作符【\】:表示用符号\,连接的内容，都是定义同一个宏的内容
 *  #:表示将参数字符串化
 *  ##：表示连接内容
 *	宏定义里有用'#'或'##'的地方宏参数不会展开，需要转换宏，进行展开
 *	inline:c++的关键字
 *	__inline: c和c++都可以用，功能与inline一致
 *	__forceinline:c和c++都可以用，不基于编译器的性能和优化分析而依赖于程序员的判断进行内联，
	但它也不保证 一定内敛，有些情况函数是肯定不能内敛的
 *	使用宏的好处：可以精简写法，易于复用；如：本例的方法可以快速定义类属性的set和get方法
 *	使用宏的坏处：
	1.在编写宏时，报错始终在使用宏的位置 
	2.报错不能确提示，对于发现错误不友好
	3.不能对宏逻辑进行断点调试
 */

#define GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName,PropertyName) \
	static std::string Get##PropertyName##Attribute() \
	{ \
		return #PropertyName; \
	}

#define GAMEPLAYATTRIBUTE_VALUE_GETTER(ClassType,PropertyName) \
	__inline ClassType Get##PropertyName() \
	{ \
		return PropertyName; \
	}
#define GAMEPLAYATTRIBUTE_VALUE_SETTER(ClassType,PropertyName) \
	__forceinline void Set##PropertyName(ClassType NewVal) \
	{ \
		PropertyName = NewVal; \
	}

 // Uses macros from AttributeSet.h
#define ATTRIBUTE_ACCESSORS(ClassName,ClassType,PropertyName) \
	GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName,PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_GETTER(ClassType,PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_SETTER(ClassType,PropertyName)


class MyClass
{
private:
	float Health;
public:
	MyClass();
	~MyClass();
	ATTRIBUTE_ACCESSORS(MyClass,float,Health)
};

MyClass::MyClass()
{
	Health = 20;
}

MyClass::~MyClass()
{
}

#define ANY_PACKAGE ((MyClass*)-1)

//#define A (2)
//#define STR(s) #s
//#define CONS(a,b) int(a##e##b)

//////////////////////////////////////////////////////////////////////////

#define A 2
#define _STR(s) #s
#define STR(s) _STR(s)/** 转换宏 [9/3/2020 ZC] */

#define _CONS(a,b) (int)a##e##b
#define CONS(a,b) _CONS(a,b)/** 转换宏 [9/3/2020 ZC] */
//////////////////////////////////////////////////////////////////////////

///////////////////////////合并匿名变量名///////////////////////////////////
#define ___ANONYMOUS1(type, var, line)  type  var##line
#define  __ANONYMOUS0(type, line)  ___ANONYMOUS1(type, _anonymous, line)
#define    ANONYMOUS(type)  __ANONYMOUS0(type, __LINE__)
//////////////////////////////////////////////////////////////////////////
int main()
{
	/** INT_MAX没有被展开 [9/3/2020 ZC] */
	printf("int max:%s\n",STR(INT_MAX));
	/** 不进行转换，编译错误，A没被展开 [9/3/2020 ZC] */
	/** 转换后，编译正确 [9/3/2020 ZC] */
	printf("CONS(a,b)=>%d\n",CONS(A,A));

	ANONYMOUS(static int);
	printf("_anonymous141=>%d \n", _anonymous140);

    EName name = EName::NAME_BoolProperty;
    
    //std::cout << name;/**报错：enum class 枚举不会隐式转化为int [8/26/2020 ZC] */
    //std::cout << (unsigned int)name;

    std::string t = LexToString(name);
    //std::cout << ANY_PACKAGE;

	MyClass Temp;
	std::cout << MyClass::GetHealthAttribute() << std::endl;
	std::cout << Temp.GetHealth() << std::endl;
	Temp.SetHealth(100);
	std::cout << Temp.GetHealth() << std::endl;

//#include "Header2.h"
    //std::cout << we;
}
